package br.com.felix.dbm.ui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;

import br.com.felix.dbm.controller.DataModelController;
import br.com.felix.dbm.controller.TableController;
import br.com.felix.dbm.database.DataModel;
import br.com.felix.dbm.database.Table;
import br.com.felix.dbm.ui.layout.DatabaseConstraintsLayout;
import br.com.felix.dbm.ui.layout.EditorEvent;
import br.com.felix.dbm.ui.layout.EditorListener;

/**
 * Database Modeling Editor for a data model.
 * */
public class EditorUi extends JInternalFrame implements EditorListener {

	private static final long serialVersionUID = 2905393355107164235L;

	private DataModel dataModel;
	private DataModelController dataModelController;
	private EditorCanvas editorCanvas;
	private EditorSideBar editorSideBar;

	public enum State {
		NORMAL, SELECTING_CENTER_TABLE, SELECTING_SINGLE_TABLE
	};

	private State state;



	/**
	 * Initializes Editor's internal state.
	 * */
	public EditorUi(DataModel dataModel) {
		super(dataModel.getName());
		this.state = State.NORMAL;
		this.dataModel = dataModel;
		this.dataModelController = new DataModelController(dataModel);
		// this.mgr = new SingleTableLayout();
		this.editorCanvas = new EditorCanvas(new DatabaseConstraintsLayout());
		this.editorCanvas.setParent(this);
		this.editorCanvas.addEditorListener(this);
		this.editorCanvas.setDataModelController(dataModelController);
		this.editorSideBar = new EditorSideBar(dataModelController);
		this.editorSideBar.setEditorSideBarDelegate(editorCanvas);
		layoutDataModel(dataModel);
		configureDefaults();
		createToolbar();
	}


	/**
	 * Adds all the tables of the datamodel.
	 * Updates UI.
	 * */
	private void layoutDataModel(DataModel dataModel) {
		for (Table table : dataModel.getTables()) {
			addTable(table);
		}
		this.dataModelController.updateTableViews();
	}



	/**
	 * Makes some default interface configurations.
	 * */
	private void configureDefaults() {
		setClosable(true);
		setLayout(new BorderLayout());
		JScrollPane jspEditorCanvas = new JScrollPane(editorCanvas);
		JPanel intermediateEditorSideBarPanel = new JPanel();
		intermediateEditorSideBarPanel.setLayout(new FlowLayout());
		intermediateEditorSideBarPanel.add(editorSideBar);
		JScrollPane jspEditorSideBar = new JScrollPane(intermediateEditorSideBarPanel);
		JSplitPane jsplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jspEditorSideBar,jspEditorCanvas);
		jsplitPane.setDividerLocation(200);
		add(jsplitPane, BorderLayout.CENTER);
	}


	/**
	 * Creates the toolbar.
	 * */
	private void createToolbar() {
		JToolBar toolbar = new JToolBar();

		JButton btnSelect = new JButton("select");
		btnSelect.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				setState(State.SELECTING_SINGLE_TABLE);
			}
		});
		toolbar.add(btnSelect);

		JButton btnCentralizeTable = new JButton("centralize");
		btnCentralizeTable.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				setState(State.SELECTING_CENTER_TABLE);
			}
		});
		toolbar.add(btnCentralizeTable);

		JButton btnTable = new JButton("new table");
		btnTable.addMouseListener(new NewTableMouseAdapter());
		toolbar.add(btnTable);

		add(toolbar, BorderLayout.PAGE_START);
	}



	/**
	 * Creates a new tableController and tableUi for the given table.
	 * Adds the controller to the datamodelController.
	 * Adds everything to the editor canvas.
	 * */
	private void addTable(Table table) {
		TableUi tableUi = new TableUi();
		TableController tableController = new TableController(table, tableUi, dataModelController);
		tableUi.setTableController(tableController);
		dataModelController.addTableController(tableController);
		editorCanvas.addTable(tableController, false);
	}

	
	/**
	 * Calls the addNewTable method.
	 * */
	class NewTableMouseAdapter extends MouseAdapter {
		@Override
		public void mouseReleased(MouseEvent e) {
			addNewTable();
		}
	}


	
	
	public void eventFired(EditorEvent e) {
		switch (e.getType()) {
			case TABLE_SELECTED:
				tableSelected((TableController) e.getSource());
				break;
		}
	}



	public void addNewTable() {
		Table table = new Table(dataModel);
		TableUi tableUi = new TableUi();
		TableController tableController = new TableController(table, tableUi, dataModelController);
		tableUi.setTableController(tableController);
		tableUi.updateView();
		dataModelController.addTableController(tableController);
		editorCanvas.addTable(tableController, true);
	}



	/**
	 * Sends events to the editor layout manager
	 * */
	public void tableSelected(TableController source) {
		switch (state) {
			case SELECTING_CENTER_TABLE: {
				dataModelController.clear();
				editorCanvas.clear();
				editorCanvas.setCentralTable(source.getModel());
				layoutDataModel(dataModel);
				getParent().getParent().validate();
				break;
			}
			case SELECTING_SINGLE_TABLE: {
				editorCanvas.selectTable(source);
				break;
			}
		}
		setState(State.NORMAL);
	}



	private void setState(State state) {
		this.state = state;
	}


	public DataModel getDataModel() {
		return dataModel;
	}

}
